package api

import (
	"net/http"

	"example.com/rest/example/dao"
	"example.com/rest/example/model"

	"github.com/gin-gonic/gin"
	"github.com/guregu/null"
	"github.com/julienschmidt/httprouter"
)

var (
	_ = null.Bool{}
)

func configTracksRouter(router *httprouter.Router) {
	router.GET("/tracks", GetAllTracks)
	router.POST("/tracks", AddTracks)
	router.GET("/tracks/:argTrackID", GetTracks)
	router.PUT("/tracks/:argTrackID", UpdateTracks)
	router.DELETE("/tracks/:argTrackID", DeleteTracks)
}

func configGinTracksRouter(router gin.IRoutes) {
	router.GET("/tracks", ConverHttprouterToGin(GetAllTracks))
	router.POST("/tracks", ConverHttprouterToGin(AddTracks))
	router.GET("/tracks/:argTrackID", ConverHttprouterToGin(GetTracks))
	router.PUT("/tracks/:argTrackID", ConverHttprouterToGin(UpdateTracks))
	router.DELETE("/tracks/:argTrackID", ConverHttprouterToGin(DeleteTracks))
}

// GetAllTracks is a function to get a slice of record(s) from tracks table in the main database
// @Summary Get list of Tracks
// @Tags Tracks
// @Description GetAllTracks is a handler to get a slice of record(s) from tracks table in the main database
// @Accept  json
// @Produce  json
// @Param   page     query    int     false        "page requested (defaults to 0)"
// @Param   pagesize query    int     false        "number of records in a page  (defaults to 20)"
// @Param   order    query    string  false        "db sort order column"
// @Success 200 {object} api.PagedResults{data=[]model.Tracks}
// @Failure 400 {object} api.HTTPError
// @Failure 404 {object} api.HTTPError
// @Router /tracks [get]
// http "http://localhost:8080/tracks?page=0&pagesize=20" X-Api-User:user123
func GetAllTracks(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	ctx := initializeContext(r)
	page, err := readInt(r, "page", 0)
	if err != nil || page < 0 {
		returnError(ctx, w, r, dao.ErrBadParams)
		return
	}

	pagesize, err := readInt(r, "pagesize", 20)
	if err != nil || pagesize <= 0 {
		returnError(ctx, w, r, dao.ErrBadParams)
		return
	}

	order := r.FormValue("order")

	if err := ValidateRequest(ctx, r, "tracks", model.RetrieveMany); err != nil {
		returnError(ctx, w, r, err)
		return
	}

	records, totalRows, err := dao.GetAllTracks(ctx, page, pagesize, order)
	if err != nil {
		returnError(ctx, w, r, err)
		return
	}

	result := &PagedResults{Page: page, PageSize: pagesize, Data: records, TotalRecords: totalRows}
	writeJSON(ctx, w, result)
}

// GetTracks is a function to get a single record from the tracks table in the main database
// @Summary Get record from table Tracks by  argTrackID
// @Tags Tracks
// @ID argTrackID
// @Description GetTracks is a function to get a single record from the tracks table in the main database
// @Accept  json
// @Produce  json
// @Param  argTrackID path int true "TrackId"
// @Success 200 {object} model.Tracks
// @Failure 400 {object} api.HTTPError
// @Failure 404 {object} api.HTTPError "ErrNotFound, db record for id not found - returns NotFound HTTP 404 not found error"
// @Router /tracks/{argTrackID} [get]
// http "http://localhost:8080/tracks/1" X-Api-User:user123
func GetTracks(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	ctx := initializeContext(r)

	argTrackID, err := parseInt32(ps, "argTrackID")
	if err != nil {
		returnError(ctx, w, r, err)
		return
	}

	if err := ValidateRequest(ctx, r, "tracks", model.RetrieveOne); err != nil {
		returnError(ctx, w, r, err)
		return
	}

	record, err := dao.GetTracks(ctx, argTrackID)
	if err != nil {
		returnError(ctx, w, r, err)
		return
	}

	writeJSON(ctx, w, record)
}

// AddTracks add to add a single record to tracks table in the main database
// @Summary Add an record to tracks table
// @Description add to add a single record to tracks table in the main database
// @Tags Tracks
// @Accept  json
// @Produce  json
// @Param Tracks body model.Tracks true "Add Tracks"
// @Success 200 {object} model.Tracks
// @Failure 400 {object} api.HTTPError
// @Failure 404 {object} api.HTTPError
// @Router /tracks [post]
// echo '{"genre_id": 92,"milliseconds": 33,"track_id": 23,"name": "WIfgYUJJcRtiSjtFxmxFfRFHU","composer": "cLaKvIOtWugjRAWfSFFkJQplm","bytes": 27,"unit_price": 0.7635213267932351,"album_id": 95,"media_type_id": 37}' | http POST "http://localhost:8080/tracks" X-Api-User:user123
func AddTracks(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	ctx := initializeContext(r)
	tracks := &model.Tracks{}

	if err := readJSON(r, tracks); err != nil {
		returnError(ctx, w, r, dao.ErrBadParams)
		return
	}

	if err := tracks.BeforeSave(); err != nil {
		returnError(ctx, w, r, dao.ErrBadParams)
	}

	tracks.Prepare()

	if err := tracks.Validate(model.Create); err != nil {
		returnError(ctx, w, r, dao.ErrBadParams)
		return
	}

	if err := ValidateRequest(ctx, r, "tracks", model.Create); err != nil {
		returnError(ctx, w, r, err)
		return
	}

	var err error
	tracks, _, err = dao.AddTracks(ctx, tracks)
	if err != nil {
		returnError(ctx, w, r, err)
		return
	}

	writeJSON(ctx, w, tracks)
}

// UpdateTracks Update a single record from tracks table in the main database
// @Summary Update an record in table tracks
// @Description Update a single record from tracks table in the main database
// @Tags Tracks
// @Accept  json
// @Produce  json
// @Param  argTrackID path int true "TrackId"
// @Param  Tracks body model.Tracks true "Update Tracks record"
// @Success 200 {object} model.Tracks
// @Failure 400 {object} api.HTTPError
// @Failure 404 {object} api.HTTPError
// @Router /tracks/{argTrackID} [put]
// echo '{"genre_id": 92,"milliseconds": 33,"track_id": 23,"name": "WIfgYUJJcRtiSjtFxmxFfRFHU","composer": "cLaKvIOtWugjRAWfSFFkJQplm","bytes": 27,"unit_price": 0.7635213267932351,"album_id": 95,"media_type_id": 37}' | http PUT "http://localhost:8080/tracks/1"  X-Api-User:user123
func UpdateTracks(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	ctx := initializeContext(r)

	argTrackID, err := parseInt32(ps, "argTrackID")
	if err != nil {
		returnError(ctx, w, r, err)
		return
	}

	tracks := &model.Tracks{}
	if err := readJSON(r, tracks); err != nil {
		returnError(ctx, w, r, dao.ErrBadParams)
		return
	}

	if err := tracks.BeforeSave(); err != nil {
		returnError(ctx, w, r, dao.ErrBadParams)
	}

	tracks.Prepare()

	if err := tracks.Validate(model.Update); err != nil {
		returnError(ctx, w, r, dao.ErrBadParams)
		return
	}

	if err := ValidateRequest(ctx, r, "tracks", model.Update); err != nil {
		returnError(ctx, w, r, err)
		return
	}

	tracks, _, err = dao.UpdateTracks(ctx,
		argTrackID,
		tracks)
	if err != nil {
		returnError(ctx, w, r, err)
		return
	}

	writeJSON(ctx, w, tracks)
}

// DeleteTracks Delete a single record from tracks table in the main database
// @Summary Delete a record from tracks
// @Description Delete a single record from tracks table in the main database
// @Tags Tracks
// @Accept  json
// @Produce  json
// @Param  argTrackID path int true "TrackId"
// @Success 204 {object} model.Tracks
// @Failure 400 {object} api.HTTPError
// @Failure 500 {object} api.HTTPError
// @Router /tracks/{argTrackID} [delete]
// http DELETE "http://localhost:8080/tracks/1" X-Api-User:user123
func DeleteTracks(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	ctx := initializeContext(r)

	argTrackID, err := parseInt32(ps, "argTrackID")
	if err != nil {
		returnError(ctx, w, r, err)
		return
	}

	if err := ValidateRequest(ctx, r, "tracks", model.Delete); err != nil {
		returnError(ctx, w, r, err)
		return
	}

	rowsAffected, err := dao.DeleteTracks(ctx, argTrackID)
	if err != nil {
		returnError(ctx, w, r, err)
		return
	}

	writeRowsAffected(w, rowsAffected)
}
